#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"


void OLED_SCLK_Clr()
{
    gpio_set_level(GPIO_NUM_9,0);
    delay_us(2);
}

void OLED_SCLK_Set()
{
    gpio_set_level(GPIO_NUM_9,1);
    delay_us(2);
}

void OLED_SDIN_Clr()
{
    gpio_set_level(GPIO_NUM_10,0);
    delay_us(2);
}

void OLED_SDIN_Set()
{
    gpio_set_level(GPIO_NUM_10,1);
    delay_us(2);
}


void IIC_Start(void)
{
    OLED_SCLK_Set();
    OLED_SDIN_Set();
    OLED_SDIN_Clr();
    OLED_SCLK_Clr();
}

/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop(void)
{
    OLED_SCLK_Set() ;
    OLED_SDIN_Clr();
    OLED_SDIN_Set();
}

void IIC_Wait_Ack(void)
{
    OLED_SCLK_Set() ;
    OLED_SCLK_Clr();
}
/**********************************************
// IIC Write byte
**********************************************/

void Write_IIC_Byte(unsigned char IIC_Byte)
{
    unsigned char i;
    unsigned char m, da;
    da = IIC_Byte;
    OLED_SCLK_Clr();

    for(i = 0; i < 8; i++)
    {
        m = da;
        m = m & 0x80;

        if(m == 0x80)
        {
            OLED_SDIN_Set();
        }
        else OLED_SDIN_Clr();

        da = da << 1;
        OLED_SCLK_Set();
        OLED_SCLK_Clr();
    }


}
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
    IIC_Start();
    Write_IIC_Byte(0x78);            //Slave address,SA0=0
    IIC_Wait_Ack();
    Write_IIC_Byte(0x00);			       //write command
    IIC_Wait_Ack();
    Write_IIC_Byte(IIC_Command);
    IIC_Wait_Ack();
    IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
    IIC_Start();
    Write_IIC_Byte(0x78);			//D/C#=0; R/W#=0
    IIC_Wait_Ack();
    Write_IIC_Byte(0x40);			//write data
    IIC_Wait_Ack();
    Write_IIC_Byte(IIC_Data);
    IIC_Wait_Ack();
    IIC_Stop();
}

/***********************Delay****************************************/
//坐标设置

void OLED_Set_Pos(unsigned char x, unsigned char y)
{
    Write_IIC_Command(0xb0 + y);
    Write_IIC_Command(((x & 0xf0) >> 4) | 0x10);
    Write_IIC_Command((x & 0x0f) | 0x01);
}
void OLED_Fill(unsigned char fill_Data)//全屏填充
{
    unsigned char m, n;

    for(m = 0; m < 8; m++)
    {
        Write_IIC_Command(0xb0 + m);		//page0-page1
        Write_IIC_Command(0x02);		//low column start address
        Write_IIC_Command(0x10);		//high column start address

        for(n = 0; n < 128; n++)
        {
            Write_IIC_Data(fill_Data);
        }
    }
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
    OLED_Fill(0x00);
}
//--------------------------------------------------------------
// Prototype      : void OLED_ON(void)
// Calls          :
// Parameters     : none
// Description    : 将OLED从休眠中唤醒
//--------------------------------------------------------------
void OLED_On(void)
{
    Write_IIC_Command(0X8D);  //设置电荷泵
    Write_IIC_Command(0X14);  //开启电荷泵
    Write_IIC_Command(0XAF);  //OLED唤醒
}
//--------------------------------------------------------------
// Prototype      : void OLED_OFF(void)
// Calls          :
// Parameters     : none
// Description    : 让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
//--------------------------------------------------------------
void OLED_OFF(void)
{
    Write_IIC_Command(0X8D);  //设置电荷泵
    Write_IIC_Command(0X10);  //关闭电荷泵
    Write_IIC_Command(0XAE);  //OLED休眠
}
//--------------------------------------------------------------
// Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Calls          : 
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16)
// Description    : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
//--------------------------------------------------------------
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)
	{
		case 8:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 122)
						return;

				OLED_Set_Pos(x,y);
				for(i=0;i<6;i++)
					Write_IIC_Data(F6x8[c][i]);
				x += 6;
				j++;
			}
		}break;
		case 16:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
						return;

				OLED_Set_Pos(x,y);
				for(i=0;i<8;i++)
					Write_IIC_Data(F8X16[c][i]);
				OLED_Set_Pos(x,y+1);
				for(i=0;i<8;i++)
					Write_IIC_Data(F8X16[c][i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}
//初始化OLED屏幕
void OLED_Init(void)
{
    gpio_config_t gpio_cfg = {0};
    gpio_cfg.intr_type = GPIO_INTR_DISABLE;         //外部中断关闭
    gpio_cfg.mode = GPIO_MODE_OUTPUT;         //推挽输出
    gpio_cfg.pin_bit_mask = 1ull <<GPIO_NUM_9;      //GPIO9
    gpio_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;  //不下拉
    gpio_cfg.pull_up_en = GPIO_PULLUP_DISABLE;       //上拉
    gpio_config(&gpio_cfg); 

    gpio_cfg.pin_bit_mask = 1ull <<GPIO_NUM_10;      //GPIO10
    gpio_config(&gpio_cfg);
    gpio_set_level(GPIO_NUM_9,0);
    gpio_set_level(GPIO_NUM_10,0);

    vTaskDelay(100); //这里的延时很重要

    Write_IIC_Command(0xAE); //display off
    Write_IIC_Command(0x20);	//Set Memory Addressing Mode
    Write_IIC_Command(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
    Write_IIC_Command(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7
    Write_IIC_Command(0xc8);	//Set COM Output Scan Direction
    Write_IIC_Command(0x00); //---set low column address
    Write_IIC_Command(0x10); //---set high column address
    Write_IIC_Command(0x40); //--set start line address
    Write_IIC_Command(0x81); //--set contrast control register
    Write_IIC_Command(0xff); //亮度调节 0x00~0xff
    Write_IIC_Command(0xa1); //--set segment re-map 0 to 127
    Write_IIC_Command(0xa6); //--set normal display
    Write_IIC_Command(0xa8); //--set multiplex ratio(1 to 64)
    Write_IIC_Command(0x3F); //
    Write_IIC_Command(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
    Write_IIC_Command(0xd3); //-set display offset
    Write_IIC_Command(0x00); //-not offset
    Write_IIC_Command(0xd5); //--set display clock divide ratio/oscillator frequency
    Write_IIC_Command(0xf0); //--set divide ratio
    Write_IIC_Command(0xd9); //--set pre-charge period
    Write_IIC_Command(0x22); //
    Write_IIC_Command(0xda); //--set com pins hardware configuration
    Write_IIC_Command(0x12);
    Write_IIC_Command(0xdb); //--set vcomh
    Write_IIC_Command(0x20); //0x20,0.77xVcc
    Write_IIC_Command(0x8d); //--set DC-DC enable
    Write_IIC_Command(0x14); //
    Write_IIC_Command(0xaf); //--turn on oled panel
    OLED_Clear();
}

